/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.dspot.declex.actions.base;

import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;

import com.dspot.declex.annotation.action.Field;
import com.dspot.declex.annotation.action.FormattedExpression;
import com.dspot.declex.api.action.runnable.OnFailedRunnable;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Handler;

/**
 * 基本模型行动持有人
 *
 * @author Administrator
 * @since 2021-07-14
 */
public class BaseModelActionHolder extends BaseFieldActionHolder {

    /**
     * 保持调用线程
     */
    private boolean keepCallingThread;

    /**
     * 查询
     */
    private String query;
    /**
     * 命令
     */
    private String orderBy;
    /**
     * 字段
     */
    private String fields;

    /**
     * arg游戏
     */
    protected Map<String, Object> args = new HashMap<>();

    /**
     * 初始化
     *
     * @param field The field annotated with {@link com.dspot.declex.annotation.Model @Model}.
     */
    @Override
    protected void init(@Field Object field) {
        super.init(field);
    }

    /**
     * 构建
     *
     * @param Done <i><b>(default)</b></i> It will be executed after the
     * {@link com.dspot.declex.annotation.Model @Model} annotated
     * field is loaded
     * @param Failed It will be executed if the
     * {@link com.dspot.declex.annotation.Model @Model} annotated field fails loading.
     */
    @Override
    protected void build(Runnable Done, OnFailedRunnable Failed) {
        super.build(Done, Failed);
    }

    /**
     * 查询
     * <i>"query"</i> that will be used as a query to load the
     * {@link com.dspot.declex.annotation.Model @Model}  annotated field.
     * If it is not provided, the "query" parameter of the
     * {@link com.dspot.declex.annotation.Model @Model}  annotation will be used
     *
     * @param query 查询
     * @return {@link BaseModelActionHolder}
     */
    public BaseModelActionHolder query(@FormattedExpression String query) {
        this.query = query;
        args.put("query", query);
        return this;
    }

    /**
     * 命令
     * "<i>orderBy</i>" that will be used to load the
     * {@link com.dspot.declex.annotation.Model @Model} annotated field.
     * If it is not provided, the "orderBy" parameter of the
     * {@link com.dspot.declex.annotation.Model @Model}  annotation will be used
     *
     * @param orderBy 命令
     * @return {@link BaseModelActionHolder}
     */
    public BaseModelActionHolder orderBy(@FormattedExpression String orderBy) {
        this.orderBy = orderBy;
        args.put("orderBy", orderBy);
        return this;
    }

    /**
     * 字段
     * "<i>fields</i>" that will be loaded by @Model annotated field.
     * If it is not provided, the "fields" parameter of the
     * {@link com.dspot.declex.annotation.Model @Model}  annotation will be used
     *
     * @param fields 字段
     * @return {@link BaseModelActionHolder}
     */
    public BaseModelActionHolder fields(@FormattedExpression String fields) {
        this.fields = fields;
        args.put("fields", fields);
        return this;
    }

    /**
     * 保持调用线程
     * Keeps the calling Thread for the Action. This avoids the automatic switch to
     * the UIThread after the Action finishes execution
     *
     * @return {@link BaseModelActionHolder}
     */
    public BaseModelActionHolder keepCallingThread() {
        keepCallingThread = true; //This will keep the Action in the thread that is executed, after finalization
        return this;
    }

    /**
     * 得到查询
     *
     * @return {@link String}
     */
    protected String getQuery() {
        return this.query;
    }

    /**
     * 得到订单
     *
     * @return {@link String}
     */
    protected String getOrderBy() {
        return this.orderBy;
    }

    /**
     * 获取字段
     *
     * @return {@link String}
     */
    protected String getFields() {
        return this.fields;
    }

    /**
     * 得到参数
     *
     * @return {@link Map<String, Object>}
     */
    protected Map<String, Object> getArgs() {
        return Collections.unmodifiableMap(args);
    }

    /**
     * 完成
     *
     * @return {@link Runnable}
     */
    @Override
    protected Runnable getDone() {
        if (!keepCallingThread && this.Done != null) {

            //Return to the main thread
            return new Runnable() {

                @Override
                public void run() {
                    if(EventRunner.getMainEventRunner().getThreadId() != Thread.currentThread().getId()) {
                        Done.run();
                    }else{
                        EventHandler handler = new EventHandler(EventRunner.getMainEventRunner());
                        handler.postSyncTask(Done);
                    }
//                    if(Looper.myLooper() == Looper.getMainLooper()) {
//                        Done.run();;
//                    } else {
//                        Handler handler = new Handler(Looper.getMainLooper());
//                        handler.post(Done);
//                    }
                }
            };

        }

        return this.Done;
    }

    /**
     * 得到失败
     *
     * @return {@link OnFailedRunnable}
     */
    @Override
    protected OnFailedRunnable getFailed() {
        if (!keepCallingThread && this.Failed != null) {

            //Return to the main thread
            return new OnFailedRunnable() {

                @Override
                public void run() {
                    Failed.e = this.e;
                    if(EventRunner.getMainEventRunner().getThreadId() != Thread.currentThread().getId()) {
                        Failed.run();;
                    }else{
                        EventHandler handler = new EventHandler(EventRunner.getMainEventRunner());
                        handler.postSyncTask(Failed);
                    }
//                    if(Looper.myLooper() == Looper.getMainLooper()) {
//                        Failed.run();;
//                    } else {
//                        Handler handler = new Handler(Looper.getMainLooper());
//                        handler.post(Failed);
//                    }
                }
            };

        }

        return this.Failed;
    }

}

